package violin.web;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.reflect.Method;

public class Resource implements Accessible {
    private final Class resourceClass;
    private final String pathTemplate;
    private final String pathRegex;

    public Resource(String path, Class<?> resourceClass) {
        this.pathTemplate = path;
        this.pathRegex = path.replaceAll("/\\{[^/]+?\\}", "/([^/]+?)");
        this.resourceClass = resourceClass;
    }

    public Class getResourceClass() {
        return resourceClass;
    }

    public boolean matches(String path) {
        return path.matches(pathRegex);
    }

    public Map<String, String> getPathParams(String uri) {
        String regex1 = pathTemplate.replaceAll("/\\{[^/]+?\\}", "/([^/]+?)");
        String regex2 = pathTemplate.replaceAll("/\\{[^/]+?\\}", "/(\\\\{[^/]+?\\\\})");

        Pattern p1 = Pattern.compile(regex1);
        Matcher m1 = p1.matcher(uri);
        Pattern p2 = Pattern.compile(regex2);
        Matcher m2 = p2.matcher(pathTemplate);
        m1.find();
        m2.find();
        Map<String, String> pathParams = new HashMap<String, String>();
        for (int i = 1; i <= m2.groupCount(); i++) {
            pathParams.put(m2.group(i), m1.group(i));
        }
        return pathParams;
    }

    public Object getResource() {
        Object resource = null;
        try {
            resource = resourceClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } finally {
            return resource;
        }
    }

    public Method resolveResourceMethod(HttpMethod httpMethod) {
        Method targetMethod = null;
        for (Method method : getResourceClass().getDeclaredMethods()) {
            if (httpMethod.matches(method)) {
                targetMethod = method;
            }
        }
        return targetMethod;
    }
}
